home *** CD-ROM | disk | FTP | other *** search
/ LiquidLibrary 2005 February / LiquidLibrary 2005 February - Disc 1.iso / pc / Portfolio Browser / Filters / PDF / LIB / gslp.ps < prev    next >
Text File  |  2003-01-03  |  20KB  |  685 lines

  1. %    Copyright (C) 1991, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2. % This software is licensed to a single customer by Artifex Software Inc.
  3. % under the terms of a specific OEM agreement.
  4.  
  5. % $RCSfile$ $Revision$
  6. % gslp.ps - format and print text
  7.  
  8. % This utility provides functionality approximately equivalent to the Unix
  9. % `enscript' program.  It prints plain text files using a single font.
  10. % It currently handles tabs and formfeeds, but not backspaces.
  11. % It will line-wrap when using fixed-pitch fonts.
  12. % It will also do kerning and width adjustment.
  13. % Standard switches implemented:
  14. %    -12BclqRr -b<header> -f<font> -F<hfont> -L<lines> -p<outfile>
  15. % Sun switches implemented:
  16. %    -T<n>    set tab width
  17. % Switches ignored:
  18. %    -GghKkmow -# -C -d -J -n -P -S -s -t -v
  19. % Switches added:
  20. %    --add-to-space <units>
  21. %        add the given number of 1/72" units to the width of each
  22. %        space (may be negative)
  23. %    --add-to-width <units>
  24. %        add the given number of 1/72" units to the width of each
  25. %        character (may be negative)
  26. %    --columns <n>
  27. %        print in <n> columns
  28. %    --detect
  29. %        treat the file as PostScript if it starts with %!
  30. %    --first-page <n>
  31. %        start printing at page <n>
  32. %    --kern <file.afm>
  33. %        kern using information from the given .AFM file
  34. %    --last-page <n>
  35. %        stop printing after page <n>
  36. %    --(heading|footing)-(left|center|right) <string>
  37. %        set the heading/footing fields; use -B first to clear
  38. %    --margin-(top|bottom|left|right) <inches>
  39. %        set a margin
  40. %    --no-eject-(file|formfeed)
  41. %        end-of-file/FF only starts a new column, not a new sheet
  42. %    --spacing <n>
  43. %        use double (n=2), triple (n=3), etc. spacing
  44. % Also, the string %# in a heading or footing is replaced with the page #.
  45. /PageNumberString (%#) def
  46.  
  47. /lpdict 150 dict def
  48. lpdict begin
  49.  
  50. % build iso-latin-1 version of a font
  51. /font-to-iso-latin-1 {    % <font> font-to-iso-latin-1 <font>
  52.     %% reencode for iso latin1; from the 2nd edition red book, sec 5.6.1
  53.     dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall
  54.     /Encoding ISOLatin1Encoding def currentdict end
  55.     dup /FontName get 80 string cvs (-ISOLatin1) concatstrings cvn 
  56.     exch definefont
  57. } def
  58.  
  59. /find-latin-font {    % <name> find-latin-font <font>
  60.   findfont font-to-iso-latin-1
  61. } def
  62.  
  63. % Define the initial values of the printing parameters.
  64.  
  65. /AddToSpace 0 def
  66. /AddToWidth 0 def
  67. /BodyFont null def        % use default
  68.   /defaultBodyFontPortrait
  69.     /Courier find-latin-font 10 scalefont def
  70.   /defaultBodyFontLandscape
  71.     /Courier find-latin-font 7 scalefont def
  72.   /defaultBodyFont
  73.     { Landscape { defaultBodyFontLandscape } { defaultBodyFontPortrait } ifelse } def
  74. /Columns 1 def
  75. /DetectFileType false def
  76. /EjectEOF true def
  77. /EjectFF true def
  78. /Footers false def
  79. /FootingLeft () def
  80. /FootingCenter () def
  81. /FootingRight () def
  82. /Headers true def
  83. /HeadingLeft () def
  84. /HeadingCenter () def
  85. /HeadingRight (page ) PageNumberString concatstrings def
  86. /HeadingFont null def        % use default
  87.   /defaultHeadingFont
  88.     /Courier-Bold find-latin-font 10 scalefont def
  89. /Kern 0 dict def        % no kerning
  90. /Landscape false def
  91. /MarginBottom 36 def        % 1/2"
  92. /MarginLeft 36 def        % 1/2"
  93. /MarginRight 36 def        % 1/2"
  94. /MarginTop 36 def        % 1/2"
  95. /MaxLines 9999 def        % max lines per page
  96. /Noisy true def            % i.e., not quiet
  97. /OutFile null def        % null = write directly to device
  98. /PageFirst 1 def
  99. /PageLast 99999 def
  100. /Spacing 1 def
  101. /Tab 8 def
  102. /Truncate false def        % wrap long lines, don't truncate
  103.  
  104. % When writing to a file, we want to write out PostScript;
  105. % when writing to the printer, we want to execute it;
  106. % some commands should be executed regardless.
  107. % lpexec provides for all this.
  108.  
  109. /lpdef {    % <name> <value> lpdef -
  110.   /def 2 true lpexec
  111. } def
  112.  
  113. /lpexec {    % <arg1> ... <argn> </op> <n> <do_always> lpexec -
  114.   OutFile null eq {
  115.     pop 1 add true
  116.   } {
  117.     /t exch def 1 add /n exch def cvx
  118.     n -1 roll dup wo
  119.     n 1 sub { n -1 roll dup wosp } repeat
  120.     (\n) ws n t
  121.   } ifelse
  122.     { pop load exec }
  123.     { { pop } repeat }
  124.   ifelse
  125. } def
  126.  
  127. /lpmoveto {    % <x> <y> lpmoveto -
  128.     % Round the coordinates for smaller output.
  129.   2 {
  130.     exch 100 mul round 100 div
  131.     dup dup cvi eq { cvi } if
  132.   } repeat
  133.   1 index X eq { neg exch pop /V 1 } { neg /M 2 } ifelse true lpexec
  134. } def
  135. /lpshow {    % <string> lpshow -
  136.   dup length 0 ne {
  137.     addspace 0 ne {
  138.       addspace 0 32 
  139.       addwidth 0 ne {
  140.     addwidth 0 6 -1 roll /awidthshow 6 true lpexec
  141.       } {
  142.     4 -1 roll /widthshow 4 true lpexec
  143.       } ifelse
  144.     } {
  145.       addwidth 0 ne {
  146.     addwidth 0 3 -1 roll /ashow 3 true lpexec
  147.       } {
  148.     OutFile null ne {
  149.       dup dup length =string length gt {
  150.         /show 1 false lpexec
  151.       } {
  152.         (S ) ws ws (\n) ws
  153.       } ifelse
  154.     } if show 
  155.       } ifelse
  156.     } ifelse
  157.   } {
  158.     pop
  159.   } ifelse
  160. } def
  161. /lpsetmyfont {
  162.   dup load setfont
  163.    OutFile null ne { cvx /setfont 1 false lpexec } { pop } ifelse
  164. } def
  165.  
  166. % Define some utility procedures.
  167.  
  168. /banner        % ypos left center right
  169.  { /HFont lpsetmyfont
  170.    /addspace 0 def /addwidth 0 def
  171.    /pairkern 0 dict def
  172.    3 -1 roll bannerstring pop 0 4 index pwidth showline2 pop
  173.    exch bannerstring pwidth exch sub 2 div 3 index pwidth showline2 pop
  174.    bannerstring
  175.         % Prevent the last character of the heading from grazing
  176.         % the right margin.
  177.         % ****** WHY DOES IT REQUIRE SO MUCH PADDING? ******
  178.    ( ) stringwidth pop 2 mul add
  179.    pwidth exch sub
  180.    3 -1 roll pwidth showline2 pop
  181.  } def
  182.  
  183. /bannerstring    % string -> string width
  184.   { PageNumberString search
  185.      { exch pop pindex 4 string cvs concatstrings exch concatstrings
  186.      }
  187.     if dup stringwidth pop
  188.   } def
  189.  
  190. /beginpage
  191.  { /lindex 0 def
  192.    /skipping pindex PageFirst ge pindex PageLast le and not def
  193.    pagex pagey Landscape {/BL} {/B} ifelse 2 true lpexec
  194.    /pagesave exch def
  195.    skipping { nulldevice   /OutFile null def } if
  196.    Headers
  197.     { lheight hdescent add
  198.       HeadingLeft HeadingCenter HeadingRight banner
  199.     } if
  200.    /BFont lpsetmyfont
  201.    /pairkern Kern def
  202.    /addspace AddToSpace def /addwidth AddToWidth def
  203.    pairkern length 0 ne {
  204.      /addspace AddToSpace lpdef /addwidth AddToWidth lpdef
  205.    } if
  206.  } def
  207.  
  208. /endpage {
  209.   lindex 0 ne {
  210.     Footers {
  211.       topskip plength sub hdescent add
  212.       FootingLeft FootingCenter FootingRight banner
  213.     } if
  214.     /E
  215.   } {
  216.     /restore
  217.   } ifelse
  218.   pagesave exch 0 true lpexec
  219.   /pindex pindex 1 add def
  220. } def
  221.  
  222. /endcolumn
  223.  { lindex colines 1 sub add colines idiv colines mul
  224.    dup llength ge { pop endpage beginpage } { /lindex exch def } ifelse
  225.  } def
  226.  
  227. /fontheight    % <font> fontheight <ascent> <height>
  228.  { gsave setfont
  229.    newpath 0 0 moveto
  230.    (|^_j) false charpath
  231.    pathbbox exch pop dup 2 index sub 4 -2 roll pop pop
  232.    grestore exch 1.25 mul exch 1.25 mul
  233.  } def
  234.  
  235. /wdict {
  236.   dup length wosp ( dict\n) ws
  237.   { (dup) ws exch wosp wosp ( put\n) ws } forall
  238. } def
  239. /wosp { ( ) ws wo } def
  240. /wo {
  241.   dup type /dicttype eq { wdict } { OutFile exch write==only } ifelse
  242. } def
  243. /ws {
  244.   OutFile exch writestring
  245. } def
  246.  
  247. /outfont {        % <name> <font> outfont -
  248.   OutFile null ne {
  249.     exch wo
  250.     dup /FontName get 
  251.     dup wosp (-ISOLatin1) ws wosp ( RE) ws
  252.     /FontMatrix get 0 get 1000 mul round cvi wosp
  253.     ( scalefont def\n) ws
  254.   } {
  255.     pop pop
  256.   }ifelse
  257. } def
  258.  
  259. /StringFF (\f) def
  260. /CharFF StringFF 0 get def
  261. /StringTAB (\t) def
  262. /CharTAB StringTAB 0 get def
  263.  
  264. /showline        % line -> leftover_line (handles \f)
  265.  {  { showline1 dup length 0 eq { exit } if
  266.       dup 0 get CharFF ne { exit } if
  267.       EjectFF { endpage beginpage } { endcolumn } ifelse
  268.       skip1
  269.     }
  270.    loop
  271.  } def
  272.  
  273. /showline1        % line -> leftover_line (handles page break)
  274.  { lindex llength eq { endpage beginpage } if
  275.    lindex colines idiv cowidth mul        % x
  276.    lindex colines mod 1 add lheight mul neg fascent sub    % y
  277.    1 index cowidth add
  278.    showline2
  279.    /lindex lindex 1 add def
  280.  } def
  281.  
  282. /setxy {
  283.   /ty exch def /tx exch def
  284. } def
  285.  
  286. /showline2 {    % string x y xlimit -> leftover_string (handles tabs)
  287.   2 index exch 5 2 roll setxy {
  288.         % Stack: xinit xlimit string
  289.     showline3 dup length 0 eq { exit } if
  290.     dup 0 get CharTAB ne { exit } if
  291.     tx 3 index sub tabwx div
  292.       0.05 add ceiling tabwx mul 3 index add ty setxy
  293.     skip1
  294.     tx 2 index ge { exit } if
  295.   } loop exch pop exch pop
  296. } def
  297.  
  298. /showline3 {    % xlimit string -> xlimit leftover_string
  299.         % (finds line break / tab / formfeed)
  300.   1 index tx sub
  301.     cwx div 0.1 add cvi 0 max 1 index length min
  302.   1 index 0 3 -1 roll getinterval
  303.     % look for \f or \t
  304.   StringFF search { exch pop exch pop } if
  305.   StringTAB search { exch pop exch pop } if
  306.   dup length 0 ne {
  307.     tx ty lpmoveto
  308.     dup pairkern length 0 eq {
  309.       lpshow
  310.     } {
  311.       { kproc } exch /kshow 2 true lpexec
  312.     } ifelse
  313.     currentpoint setxy
  314.   } if
  315.   length dup 2 index length exch sub getinterval
  316. } def
  317.  
  318. /kproc {    % <char1> <char2> kproc -
  319.   pairkern currentfont /Encoding get 3 index get
  320.   2 copy known {
  321.     get currentfont /Encoding get 2 index get
  322.     2 copy known {
  323.       get currentfont /FontMatrix get 0 get mul
  324.     } {
  325.       pop pop 0
  326.     } ifelse
  327.   } {
  328.     pop pop 0
  329.   } ifelse
  330.   addwidth add 2 index 32 eq { addspace add } if
  331.   dup 0 eq { pop } { 0 rmoveto } ifelse
  332.   pop pop
  333. } def
  334.  
  335. /skip1
  336.  { dup length 1 sub 1 exch getinterval
  337.  } def
  338.  
  339. /e== {        % <object> e== - -- print an object to stderr
  340.   (%stderr) (w) file dup 3 -1 roll write==only flushfile
  341. } def
  342.  
  343. /eprint {    % <string> eprint - -- print a string to stderr
  344.   (%stderr) (w) file dup 3 -1 roll writestring flushfile
  345. } def
  346.  
  347. % Read kerning information from a .AFM file.
  348.  
  349. /readkern {    % <afmfile> readkern <pairkerndict>
  350.   /mfilename 1 index def
  351.   (r) file /mfile exch def
  352.   mfile =string readline pop
  353.   (StartFontMetrics ) anchorsearch {
  354.     pop pop
  355.     /kdict 256 dict def
  356.     { mfile =string readline pop
  357.       (EndFontMetrics) anchorsearch { pop pop exit } if
  358.       (KPX ) anchorsearch {
  359.     pop token pop cvlit /char1 exch def
  360.     token pop cvlit /char2 exch def
  361.     token pop /kern exch def pop
  362.     kdict char1 .knownget not {
  363.       5 dict kdict char1 2 index .growput
  364.     } if
  365.     char2 kern .growput
  366.       } {
  367.     pop
  368.       } ifelse
  369.     } loop kdict
  370.   } {
  371.     pop
  372.     mfilename eprint ( does not begin with StartFontMetrics.\n) eprint
  373.     0 dict
  374.   } ifelse
  375.   mfile closefile
  376. } def
  377.  
  378. % The main printing procedure
  379.  
  380. /doFirst true def
  381. /prevBFont null def
  382. /prevHFont null def
  383.  
  384. /lpfirst {    % - lpfirst -
  385. % Define some abbreviating procedures.
  386.   /B {save 3 1 roll translate /X 0 def} lpdef
  387.   /BL {save 3 1 roll 90 rotate translate /X 0 def} lpdef
  388.   /E {showpage restore} lpdef
  389.   /V {neg X exch moveto} lpdef
  390.   /M {/X 2 index def neg moveto} lpdef
  391.   /S {currentfile =string readline pop show} lpdef
  392.   /RE {        % <isoname> <fontname> RE <font>
  393.     findfont
  394.     %% reencode for iso latin1; from the 2nd edition red book, sec 5.6.1
  395.     dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall
  396.     /Encoding ISOLatin1Encoding def currentdict end
  397.     definefont
  398.   } lpdef
  399. } def
  400.  
  401. /lp {        % file initial_chars ->
  402.   /lpline exch def
  403.   /lpfile exch def
  404.  
  405.   doFirst { lpfirst /doFirst false def } if
  406.  
  407. % Initialize the device and fonts.
  408.   /BFont
  409.     BodyFont null eq { defaultBodyFont } { BodyFont } ifelse def
  410.   BFont prevBFont ne {
  411.     /BFont BFont outfont
  412.     /prevBFont BFont def
  413.   } if
  414.   Headers Footers or {
  415.     /HFont
  416.       HeadingFont null eq { defaultHeadingFont } { HeadingFont } ifelse def
  417.     HFont prevHFont ne {
  418.       /HFont HFont outfont
  419.       /prevHFont HFont def
  420.     } if
  421.   } if
  422.   save
  423.  
  424. % Get the layout parameters.
  425.    clippath
  426.    gsave    % for possible rotation
  427.    Landscape { 90 rotate } if
  428.    BFont setfont ( ) stringwidth pop /cwx exch def
  429.      cwx Tab mul /tabwx exch def
  430.    BFont fontheight /fheight exch def /fascent exch def
  431.    Headers Footers or { HFont fontheight } { 0 0 } ifelse
  432.      /hheight exch def /hascent exch def
  433.      /hdescent hheight hascent sub def
  434.    fheight Spacing mul /lheight exch def
  435.    Headers { hheight lheight add } { 0 } ifelse
  436.      /topskip exch def
  437.    Footers { hheight lheight add } { 0 } ifelse
  438.      /botskip exch def
  439.    /pskip topskip botskip add def
  440.     % Translate the page so that (0,0) corresponds to
  441.     % the top of the topmost body line.
  442.    pathbbox
  443.      2 index sub MarginBottom MarginTop add sub /plength exch def
  444.      2 index sub MarginLeft MarginRight add sub /pwidth exch def
  445.      pwidth Columns div /cowidth exch def
  446.      exch MarginLeft add
  447.      exch MarginBottom add plength add topskip sub
  448.      /pagey exch def /pagex exch def
  449.    plength pskip sub lheight div cvi MaxLines min
  450.      dup /colines exch def
  451.      Columns mul /llength exch def
  452.    grestore
  453.    OutFile null ne { nulldevice } if
  454.  
  455. % Print layout
  456.    Noisy
  457.     { (Page height = ) eprint llength e==
  458.       (.\n) eprint flush
  459.     } if
  460.  
  461. % Write the kerning table, if relevant.
  462.    OutFile null ne Kern length 0 ne and {
  463.      (/kproc) ws /kproc load wosp ( def\n) ws
  464.      (/pairkern) ws Kern wosp ( def\n) ws
  465.    } if
  466.  
  467. % Disable stack recording so we can use stopped with readline.
  468.    $error /recordstacks false put
  469.  
  470. % Initialize for the first page.
  471.    /lbuf 1000 string def
  472.    /pindex 1 def
  473.    beginpage
  474.  
  475. % Iterate through the file.
  476.    lpline
  477.     { dup length /pos exch def
  478.       lbuf exch 0 exch putinterval
  479.        { lpfile lbuf pos lbuf length pos sub getinterval readline } stopped
  480.        {    % Filled the line before a CR or EOF.
  481.          exch pop showline
  482.        }
  483.        {    % Reached CR and/or EOF first.
  484.          exch length pos add lbuf exch 0 exch getinterval
  485.      1 index { showline } if        % omit final empty line
  486.       { dup length 0 eq Truncate or { pop () exit } if
  487.         showline
  488.       }
  489.      loop
  490.      exch not { exit } if
  491.        }
  492.       ifelse
  493.     } loop
  494.    pop
  495.  
  496. % Wrap up.
  497. %**************** WHY IS THIS COMMENTED OUT? ****************
  498. %   EjectEOF { endpage } { endcolumn } ifelse
  499.    endpage
  500.    restore
  501.  
  502. } def
  503.  
  504. end
  505.  
  506. % Usage: <file> lp
  507. %   prints <file> using the current parameter settings.
  508. % Usage: [ <arg1> ... <argn> ] lpcommand
  509. %   interprets args like a command line.
  510.  
  511. /lp { save   lpdict begin () lp end   restore } def
  512.  
  513. lpdict begin
  514.  
  515. /splitfn        % (FontNNN) -> <font>
  516.  { dup /arg exch def length
  517.     { dup 0 le { exit } if
  518.       dup 1 sub arg exch get dup 48 ge exch 59 le and not { exit } if
  519.       1 sub
  520.     } loop
  521.    arg exch 0 exch getinterval dup cvn find-latin-font
  522.    exch arg exch anchorsearch pop pop cvr scalefont
  523.  } def
  524.  
  525. % Parse the command line switches.
  526.  
  527. /doswitch    % argn ... arg1 (-?) restofswitch ->
  528.  { exch dup cvn lpdict exch known
  529.     { cvn load exec }
  530.     { exch pop (Unknown switch: ) eprint eprint (\n) eprint }
  531.    ifelse
  532.  } def
  533.  
  534. /more        % argn ... arg1 restofswitch ->
  535.  { dup length 0 ne
  536.     { (- ) dup 1 3 index 0 get put
  537.       exch dup length 1 sub 1 exch getinterval
  538.       doswitch
  539.     }
  540.     { pop
  541.     }
  542.    ifelse
  543.  } def
  544.  
  545. /-- { (--) exch concatstrings
  546.       dup cvn lpdict exch known
  547.        { cvn load exec }
  548.        { (Unknown switch: ) eprint eprint (\n) eprint }
  549.       ifelse
  550.     } def
  551. /--add-to-space { cvr /AddToSpace exch def } def
  552. /--add-to-width { cvr /AddToWidth exch def } def
  553. /--columns { cvi 1 max /Columns exch def } def
  554. /--detect { /DetectFileType true def } def
  555. /--first-page { cvi /PageFirst exch def } def
  556. /--footing-center { /FootingCenter exch def   /Footers true def } def
  557. /--footing-left { /FootingLeft exch def   /Footers true def } def
  558. /--footing-right { /FootingRight exch def   /Footers true def} def
  559. /--heading-center { /HeadingCenter exch def   /Headers true def } def
  560. /--heading-left { /HeadingLeft exch def   /Headers true def } def
  561. /--heading-right { /HeadingRight exch def   /Headers true def } def
  562. /--kern { readkern /Kern exch def } def
  563. /--last-page { cvi /PageLast exch def } def
  564. /--margin-bottom { cvr 72.0 mul /MarginBottom exch def } def
  565. /--margin-left { cvr 72.0 mul /MarginLeft exch def } def
  566. /--margin-right { cvr 72.0 mul /MarginRight exch def } def
  567. /--margin-top { cvr 72.0 mul /MarginTop exch def } def
  568. /--no-eject-file { /EjectEOF false def } def
  569. /--no-eject-formfeed { /EjectFF false def } def
  570. /--spacing { cvr /Spacing exch def } def
  571.  
  572. /-# { pop } def        % ignore
  573. /-+ { -- } def
  574. (-1)cvn { /Columns 1 def   more } def
  575. (-2)cvn { /Columns 2 def   more } def
  576. /-b { /HeadingLeft exch def   /HeadingCenter () def   /HeadingRight PageNumberString def
  577.       /Headers true def
  578.       /break true def
  579.     } def
  580. /-B { /HeadingLeft () def   /HeadingCenter () def   /HeadingRight () def
  581.       /Headers false def
  582.       /FootingLeft () def   /FootingCenter () def   /FootingRight () def
  583.       /Footers false def
  584.       /break true def
  585.       more
  586.     } def
  587. /-C { pop } def        % ignore
  588. /-c { /Truncate true def   more } def
  589. /-d { pop } def        % ignore
  590. /-f { splitfn /BodyFont exch def } def
  591. /-F { splitfn /HeadingFont exch def } def
  592. /-G { more } def    % ignore
  593. /-g { more } def    % ignore
  594. /-h { more } def    % ignore
  595. /-J { pop } def        % ignore
  596. /-K { more } def    % ignore
  597. /-k { more } def    % ignore
  598. /-l { 66 -L -B } def
  599. /-L { cvi /MaxLines exch def } def
  600. /-m { more } def    % ignore
  601. /-n { pop } def        % ignore
  602. /-o { more } def    % ignore
  603. /-p { (w) file /OutFile exch def   OutFile (%!\n) writestring } def
  604. /-P { pop } def        % ignore
  605. /-q { /Noisy false def   more } def
  606. /-r { /Landscape true def   more } def
  607. /-R { /Landscape false def   more } def
  608. /-S { pop } def        % ignore
  609. /-s { pop } def        % ignore
  610. /-T { cvi /Tab exch def } def
  611. /-v { pop } def        % ignore
  612. /-w { more } def    % ignore
  613.  
  614. /lp1        % filename ->
  615.  { break not { dup /HeadingLeft exch def } if
  616.    Noisy
  617.     { (Printing ) eprint dup eprint (\n) eprint 
  618.     } if
  619.    (r) file
  620.         % If requested, check for a PostScript file.
  621.    DetectFileType
  622.     { dup 2 string readstring pop dup (%!) eq
  623.        {    % Yes, it's a PostScript file.
  624.          pop dup 80 string readline pop pop cvx exec
  625.        }
  626.        { lp
  627.        }
  628.       ifelse
  629.     }
  630.     { () lp
  631.     }
  632.    ifelse
  633.  } bind def
  634.  
  635. /lpcstring 100 string def
  636.  
  637. end
  638.  
  639. /lpcommand        % <[arg1 ... argn]> lpcommand <any_printed>
  640.  {    % Push the commands on the stack in reverse order
  641.    mark exch
  642.    dup length 1 sub -1 0 { 1 index exch get exch } for pop
  643.    lpdict begin
  644.    /any false def
  645.    /break false def
  646.     { dup mark eq { pop exit } if
  647.       dup length 2 ge { dup 0 get (-) 0 get eq } { false } ifelse
  648.        { dup 0 2 getinterval
  649.          exch dup length 2 sub 2 exch getinterval
  650.      doswitch
  651.        }
  652.        { dup  /matched false def
  653.           { /matched true def   /any true def   lp1 } lpcstring filenameforall
  654.      matched { pop } { lp1 } ifelse        % let the error happen
  655.        }
  656.       ifelse
  657.     } loop
  658.    OutFile null ne
  659.     { OutFile (%stdout) (w) file ne { OutFile closefile } if
  660.       /OutFile null def
  661.     } if
  662.    any
  663.    end
  664.  } def
  665.  
  666. [ shellarguments
  667.  { ] dup length 0 ne { lpcommand } { false } ifelse not
  668.     { (%stderr) (w) file
  669.       [ (Usage: )
  670.     /PROGNAME where { pop PROGNAME } { (gslp) } ifelse
  671.     ( [-12BclqRr] [-b<header>] [-f<font>] [-F<hfont>]\n)
  672.     (        [-L<lines>] [-p<outfile>] [-T<tabwidth>]\n)
  673.     (        [--add-to-(space|width) <units>] [--columns <n>]\n)
  674.     (        [--detect] [--first-page <page#>] [--last-page <page#>]\n)
  675.     (        [--(heading|footing)-(left|right|center) <string>]\n)
  676.     (        [--kern <afmfile>] [--margin-(top|bottom|left|right) <inches>]\n)
  677.     (        [--no-eject-(file|formfeed)] [--spacing <n>] file1 ... filen\n)
  678.       ] { 2 copy writestring pop } forall dup flushfile closefile
  679.     }
  680.    if
  681.  }
  682.  { pop }
  683. ifelse
  684.